package pl.edu.agh.ssm.monitor;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

import pl.edu.agh.ssm.monitor.data.Session; //import pl.edu.agh.ssm.monitor.data.SessionConnection;
import pl.edu.agh.ssm.monitor.data.SessionDataContainer;
import pl.edu.agh.ssm.monitor.data.SessionNode;
import pl.edu.agh.ssm.monitor.data.SessionNodeType;
import pl.edu.agh.ssm.monitor.data.SessionType;
import pl.edu.agh.ssm.monitor.utils.SessionDataUtils;

public class SessionStateAgent extends Thread {

	private SessionDataContainer<Session> sessions = null;
	private final static long NODE_TIMEOUT = 30000; // 30[s]
	private final static long TIME_PERIOD = 3000;

	public SessionStateAgent() {
		sessions = SessionMonitorApp.getApplication().getManager()
				.createContainer(Session.class);
	}

	@Override
	public void run() {
		while (!this.isInterrupted()) {
			try {
				Thread.sleep(TIME_PERIOD);
				// System.out.println("Agent run");
				for (Session session : sessions.getAll()) {
					if (session.getSessionType() != SessionType.RTSP_SESSION) {
						// check nodes and their types
						List<SessionNode> nodesToRemove = new LinkedList<SessionNode>();
						for (SessionNode node : session.getNodes().getAll()) {
							HashMap<SessionNodeType, Long> stateMap = node
									.getStates();
							boolean changed = false;
							for (SessionNodeType nodeType : SessionNodeType
									.values()) {
								if (stateMap.containsKey(nodeType)) {
									if (!SessionDataUtils.isValidTime(nodeType,
											stateMap.get(nodeType))) {
										stateMap.remove(nodeType);
										changed = true;
									}
								}
							}
							if (changed) {
//								System.out.println("AGENT Update node: "
//										+ node.getSsrc() + ", from type: "
//										+ node.getNodeType());
								node.setNodeTypeDirectly(SessionDataUtils
										.getSessionNodeType(stateMap));
//								System.out.println("To type: "
//										+ node.getNodeType());
								session.updateNode(node);
							}
							
							if(System.currentTimeMillis() - node.getLastReportTime() > NODE_TIMEOUT) {
								nodesToRemove.add(node);
							}

						}
						for(SessionNode sNode : nodesToRemove) {
							session.removeNode(sNode);
						}
					}
					
					
				}

			} catch (InterruptedException ex) {
//				ex.printStackTrace();
			}
		}

	}

}
